import com.google.gson.*;

import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * 城市数据结构类
 * ======================================
 * USER NAME: ving <904679843@qq.com>
 * DATE TIME: 17-9-9 下午2:28
 * ======================================
 */
public class City {

    private double EARTH_RADIUS = 6378.137;

    private int cityNum;
    private int[] id;
    private String[] city;
    private double[] x;
    private double[] y;
    private double[] latitude;
    private double[] longitude;
    private JsonArray[] unline;
    private double[][] distance; //距离矩阵

    /**
     * City 构造函数，解析json数据
     * @param FlieName
     */
    public City(String FlieName) {
        try {
            JsonParser parser = new JsonParser();  //创建json解析器
            JsonObject object = (JsonObject) parser.parse(new FileReader(FlieName));
            JsonArray jsonArray = object.get("data").getAsJsonArray();
            cityNum = jsonArray.size();
            id = new int[cityNum];
            city = new String[cityNum];
            x = new double[cityNum];
            y = new double[cityNum];
            latitude = new double[cityNum];
            longitude= new double[cityNum];
            unline = new JsonArray[cityNum];
            for (int i = 0; i < cityNum; i++) {
                JsonObject subObject = jsonArray.get(i).getAsJsonObject();
                id[i] = subObject.get("id").getAsInt();
                city[i] = subObject.get("city").getAsString();
                x[i] = subObject.get("x").getAsDouble();
                y[i] = subObject.get("y").getAsDouble();
                latitude[i] = subObject.get("latitude").getAsDouble();
                longitude[i] = subObject.get("longitude").getAsDouble();
                unline[i] = subObject.get("unline").getAsJsonArray();
            }
        } catch (JsonIOException | JsonSyntaxException | FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        distance = new double[cityNum][cityNum];
        initDistance();
    }

    /**
     * 初始化 计算距离矩阵
     */
    public void initDistance() {
        for (int i = 0; i < cityNum; i++) {
            for (int j = 0; j < cityNum; j++) {
                if (i == j) {
                    distance[i][j] = 0;
                } else {
                    if (useArraysBinarySearch(unline[i], j)) {
                        distance[i][j] = -1;
                    } else {
                        distance[i][j] = GetDistance(latitude[i],longitude[i],latitude[j],longitude[j]);
                    }
                }
            }
        }
    }

    /**
     * 判断目标数是否在jsonArray中
     *
     * @param jsonArray
     * @param targetValue
     * @return
     */
    public boolean useArraysBinarySearch(JsonArray jsonArray, int targetValue) {
        for (int i = 0; i < jsonArray.size(); i++) {
            if (jsonArray.get(i).getAsInt() == targetValue) {
                return true;
            }
        }
        return false;
    }

    public double rad(double d){
        return d * Math.PI / 180.0;
    }

    /**
     * 计算经纬度两点之间的距离  以km为单位返回
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return
     */
    public double GetDistance(double lat1, double lng1, double lat2, double lng2){
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
                Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /**
     * 获取距离矩阵
     * @return
     */
    public double[][] getDistance() {
        return distance;
    }

    /**
     * 获取城市数
     * @return
     */
    public int getCityNum() {
        return cityNum;
    }

    /**
     * 获取全部城市id
     * @return
     */
    public int[] getId() {
        return id;
    }

    /**
     * 获取全部城市名
     * @return
     */
    public String[] getCity() {
        return city;
    }

    /**
     * 获取全部城市在图片上显示的x坐标
     * @return
     */
    public double[] getX() {
        return x;
    }

    /**
     * 获取全部城市在图片上显示的y坐标
     * @return
     */
    public double[] getY() {
        return y;
    }

}
